////////////////////////////////////////////////////////////////////////
// This file is part of the simpleSID framework
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
//
// Copyright (c)Richard White, 2009
// See License.txt for a disclaimer of all warranties
// and licensing information

class Envelope
{
private:
	static const unsigned short m_wLFSRTable[];
	static const unsigned char m_byExponentialPeriodTable[];
	static const unsigned char m_bySustainLevelTable[];

	unsigned short m_wLFSR;
	unsigned short m_wLFSRPeriod;
	unsigned char m_byExponentialCounter;
	unsigned char m_byExponentialPeriod;
	unsigned char m_byEnvelopeLevel;
	unsigned char m_bySustainLevel;
	bool m_bGate;
	bool m_bActive;
	
	//These Registers are only a nibble in size
	unsigned char m_byAttack;
	unsigned char m_byDecay;
	unsigned char m_bySustain;
	unsigned char m_byRelease;

	enum State{	kAttack, kDecay, kSustain, kRelease	} m_State;
	
public:
	Envelope();
	virtual ~Envelope();
	void Reset();

	void Process();
	unsigned char Output(); //Das 8bit output

	void SetGate(bool bGate);
	void SetAttackDecay(unsigned char byAD);
	void SetSustainRelease(unsigned char bySR);
	
	unsigned char GetAttack();
	unsigned char GetDecay();
	unsigned char GetSustain();
	unsigned char GetRelease();
	
	//These are nibbles
	void SetAttack(unsigned char byAttack);
	void SetDecay(unsigned char byDecay);
	void SetSustain(unsigned char bySustain);
	void SetRelease(unsigned char byRelease);

	unsigned char ReadEnvelope();

};